use axum::{
    http::{header, HeaderValue, StatusCode, Uri},
    response::{IntoResponse, Response},
    routing::get,
    Router,
};
use log::info;
use rust_embed::Embed;
use tokio::net::TcpListener;

use crate::{error::AppErr, global::app_init};
mod api;
mod status;
mod utils;


const SERVER_ADDR: &'static str = "0.0.0.0:8080";

pub async fn run(path: &str) -> Result<(), AppErr> {

    app_init(path).await?;

    let serve = TcpListener::bind(SERVER_ADDR).await?;
    let app = Router::new()
        .nest("/api", api::register())
        .route("/ws/status", get(status::on_status_connect))
        .fallback(get(static_handler));

    info!("server run:{}", SERVER_ADDR);
    axum::serve(serve, app).await?;

    Ok(())
}

#[derive(Embed)]
#[folder = "./bv3backweb/dist"]
struct WebAsset;

async fn static_handler(uri: Uri) -> Response {
    let path = uri.path().trim_start_matches("/");
    let path2 = if path.is_empty() { "index.html" } else { path };

    if let Some(s) = WebAsset::get(path2) {
        let mut resp = s.data.into_response();
        let ct = HeaderValue::from_str(s.metadata.mimetype());
        if let Ok(ct) = ct {
            resp.headers_mut().insert(header::CONTENT_TYPE, ct);
        }
        return resp;
    }

    (StatusCode::NOT_FOUND, "404 Not Found").into_response()
}
